﻿using System;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Media.Animation;

namespace MvvmFx.Common.ViewModels.Commands
{
    /// <summary>
    /// Silverlight Behavior to begin a storyboard after a command executes
    /// </summary>
    public class StoryboardCommandHandlerBehavior : Behavior<FrameworkElement>
    {
        #region Private Fields

        private IViewModelCommand _command;
        private StoryboardCommandHandler _storyboardCommandHandler;

        #endregion

        #region Dependency Properties

        /// <summary>
        /// Gets or sets the value of the <see cref=”CommandPath”/> property.
        /// </summary>
        public string CommandPath
        {
            get { return (string)GetValue(CommandPathProperty); }
            set { SetValue(CommandPathProperty, value); }
        }

        /// <summary>
        /// The <see cref="CommandPathProperty" /> dependency property registered with the 
        /// Silverlight property system.
        /// </summary>
        public static readonly DependencyProperty CommandPathProperty =
            DependencyProperty.Register("CommandPath", typeof(string), typeof(StoryboardCommandHandlerBehavior), new PropertyMetadata(null, OnCommandPathChanged));

        private static void OnCommandPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behavior = (StoryboardCommandHandlerBehavior)d;
            behavior.OnCommandPathChanged();
        }

        private void OnCommandPathChanged()
        {
        }

        /// <summary>
        /// Gets or sets the value of the <see cref=”Storyboard”/> property.
        /// </summary>
        public string Storyboard
        {
            get { return (string)GetValue(StoryboardProperty); }
            set { SetValue(StoryboardProperty, value); }
        }

        /// <summary>
        /// The <see cref="StoryboardProperty" /> dependency property registered with the 
        /// Silverlight property system.
        /// </summary>
        public static readonly DependencyProperty StoryboardProperty =
            DependencyProperty.Register("Storyboard", typeof(string), typeof(StoryboardCommandHandlerBehavior), new PropertyMetadata(null, OnStoryboardChanged));

        private static void OnStoryboardChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behavior = (StoryboardCommandHandlerBehavior)d;
            behavior.OnStoryboardChanged();
        }

        private void OnStoryboardChanged()
        {
        }

        /// <summary>
        /// Gets or sets the value of the <see cref=”CommandType”/> property.
        /// </summary>
        public string CommandType
        {
            get { return (string)GetValue(CommandTypeProperty); }
            set { SetValue(CommandTypeProperty, value); }
        }

        /// <summary>
        /// The <see cref="CommandTypeProperty" /> dependency property registered with the 
        /// Microsoft Presentation Foundation (WPF) property system.
        /// </summary>
        public static readonly DependencyProperty CommandTypeProperty =
            DependencyProperty.Register("CommandType", typeof(string), typeof(StoryboardCommandHandlerBehavior), new PropertyMetadata(null, OnCommandPathChanged));

        private static void OnCommandTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        #endregion

        protected override void OnAttached()
        {
            base.OnAttached();

            this.AssociatedObject.Loaded += AssociatedObject_Loaded;
        }

        void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.AssociatedObject == null)
                return;

            if (_command != null)
            {
                Command.RemoveHandler(_command, _storyboardCommandHandler);
            }

            var storyboard = this.AssociatedObject.Resources[Storyboard] as Storyboard;
            if (storyboard != null)
            {
                _storyboardCommandHandler = new StoryboardCommandHandler(storyboard);
            }

            var dataContext = this.AssociatedObject.DataContext;
            if (dataContext != null)
            {
                var type = dataContext.GetType();
                var propInfo = type.GetProperty(CommandPath);
                if (propInfo != null)
                {
                    _command = propInfo.GetValue(dataContext, null) as IViewModelCommand;
                    if (_command != null)
                    {
                        Command.AddHandler(_command, _storyboardCommandHandler);
                    }
                }
            }
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
        }
    }
}
